﻿using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using PagedList;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using TMV.Models.Input;
using TMV.Models.View.Role;
using TMV.Services;

namespace TMV.Controllers
{
    public class RoleController : Controller
    {
        // initialize service object
        IRoleService roleService;
        IAccountService accountService;
        ApplicationUserManager userManager;
        public ApplicationUserManager UserManager
        {
            get
            {
                return userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                userManager = value;
            }
        }

        public RoleController(IRoleService roleService, IAccountService accountService)
        {
            this.roleService = roleService;
            this.accountService = accountService;
        }

        // GET: Role
        //[ApplicationAuthorize(Permissions = Rights.View + Modules.Role)]
        public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)
        {
            ViewBag.CurrentSort = sortOrder;
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";

            if (!String.IsNullOrEmpty(searchString))
            {
                page = 1;
            }
            else
            {
                searchString = currentFilter;
            }

            ViewBag.CurrentFilter = searchString;

            var records = roleService.Get();

            // search
            if (!String.IsNullOrEmpty(searchString))
            {
                var keyword = searchString.ToLower();
                records = records.Where(s => s.Name.ToLower().Contains(keyword));
            }
            //

            // sort
            switch (sortOrder)
            {
                case "name_desc":
                    records = records.OrderByDescending(s => s.Name);
                    break;
                default:  // Name ascending 
                    records = records.OrderBy(s => s.Name);
                    break;
            }
            //

            var roles = records.Select(x => new RoleViewModel
            {
                Id = x.Id,
                Name = x.Name
            });

            int pageSize = 5;
            int pageNumber = (page ?? 1);

            return View(roles.ToPagedList(pageNumber, pageSize));
        }

        // GET: Role/Details/name
        //[ApplicationAuthorize(Permissions = Rights.View + Modules.Role)]
        public ActionResult Details(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            ApplicationRole applicationRole = roleService.GetByName(id);
            if (applicationRole == null)
            {
                return HttpNotFound();
            }
            var model = new RoleViewModel(applicationRole);
            return View(model);
        }

        // GET: Role/Create
        //[ApplicationAuthorize(Permissions = Rights.Create + Modules.Role)]
        public ActionResult Create()
        {
            return View();
        }

        // POST: Role/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        //[ApplicationAuthorize(Permissions = Rights.Create + Modules.Role)]
        public ActionResult Create([Bind(Include = "Name")] RoleViewModel role)
        {
            if (ModelState.IsValid)
            {
                ApplicationRole applicationRole = roleService.GetByName(role.Name);
                if (applicationRole != null) // exists
                {
                    string message = "That role name has already been used";
                    ModelState.AddModelError("Name", message);
                    return View();
                }

                var _role = new ApplicationRole(role.Name);
                roleService.Insert(_role);
                return RedirectToAction("Index");
            }

            return View(role);
        }

        // GET: Role/Edit/5
        //[ApplicationAuthorize(Permissions = Rights.Modify + Modules.Role)]
        public ActionResult Edit(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            // It's actually the Role.Name tucked into the id param:           
            ApplicationRole role = roleService.GetByName(id);
            if (role == null)
            {
                return HttpNotFound();
            }
            var model = new RoleViewModel(role);

            // load current users who are assigned to this role
            //var users = accountService.Get(u => u.Roles.Select(r => r.RoleId).Contains(role.Id)).Select(u => new AssociateViewModel
            //{
            //    Id = u.Id,
            //    DisplayName = u.DisplayName
            //});
            //model.CurrentUsers = users;

            return View(model);
        }

        // POST: Role/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        //[ApplicationAuthorize(Permissions = Rights.Modify + Modules.Role)]
        public ActionResult Edit([Bind(Include = "Name,OriginalName,SelectedUsers")] RoleViewModel role)
        {
            if (ModelState.IsValid)
            {
                if (role.Name != role.OriginalName)
                {
                    ApplicationRole applicationRole = roleService.GetByName(role.Name);
                    if (applicationRole != null) // exists
                    {
                        string message = "That role name has already been used";
                        ModelState.AddModelError("Name", message);
                        return View(role);
                    }

                    var _role = roleService.GetByName(role.OriginalName);
                    _role.Name = role.Name;
                    roleService.Update(_role);
                }

                // users (userId)
                //var users = role.SelectedUsers.Split(',');
                //foreach (var user in users)
                //{
                //    var rolesForUser = UserManager.GetRoles(user);
                //    if (!rolesForUser.Contains(role.Name))
                //    {
                //        var result = UserManager.AddToRole(user, role.Name);
                //    }
                //}

                return RedirectToAction("Index");
            }
            return View(role);
        }

        // GET: Role/Delete/5
        //[ApplicationAuthorize(Permissions = Rights.Delete + Modules.Role)]
        public ActionResult Delete(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            ApplicationRole applicationRole = roleService.GetByName(id);
            if (applicationRole == null)
            {
                return HttpNotFound();
            }
            var model = new RoleViewModel(applicationRole);
            return View(model);
        }

        // POST: Role/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        //[ApplicationAuthorize(Permissions = Rights.Delete + Modules.Role)]
        public ActionResult DeleteConfirmed(string id)
        {
            var role = roleService.GetByName(id);
            roleService.Delete(role);
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                UserManager.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}